package org.example.demo3.demos.web.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.annotation.OrderBy;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.extension.toolkit.Db;
import org.example.demo3.demos.web.Mapper.UserMapper;
import org.example.demo3.demos.web.domain.dto.PageDto;
import org.example.demo3.demos.web.domain.dto.UserFormDTO3;
import org.example.demo3.demos.web.domain.query.UserQuery2;
import org.example.demo3.demos.web.domain.vo.AddressVO;
import org.example.demo3.demos.web.domain.vo.UserVO;
import org.example.demo3.demos.web.entity.Address;
import org.example.demo3.demos.web.entity.User;
import org.example.demo3.demos.web.enums.UserStatus;
import org.example.demo3.demos.web.service.IAddressService;
import org.example.demo3.demos.web.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collections;
import java.util.List;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService{
    @Autowired
    private IAddressService iAddressService;
    @Override
    public void UserMinuteYuE(String id, int money) {
        // 1.查询用户
        User user = this.getById(id);
        // 2.校验状态
        if(user == null || user.getStatus() == UserStatus.FORZEN){ // 冻结不处理
            throw new RuntimeException("用户状态异常");
        }
        // 3.校验余额
        if(user.getPassword() <= money){ // 小于这个数就无法抵扣，给个报错
            throw new RuntimeException("用户余额不够");
        }

        // 4.扣减额度
//        UpdateWrapper<User> userUpdateWrapper = new UpdateWrapper<>(); // 自己写的，也可以使用。
//        userUpdateWrapper.eq("id",id);
//        userUpdateWrapper.setSql("password = password - 200");
//        this.update(userUpdateWrapper);
        baseMapper.MinuteYeSelf(id,money);
    }

    @Override
    public List<User> duoTiaoJianFn(String name, Integer status, Integer minPassword, Integer maxPassword) {
/*        LambdaQueryWrapper<User> userLambdaQueryWrapper = new LambdaQueryWrapper<>();
        userLambdaQueryWrapper.eq(name != null,User::getUsername,name)
                .eq(status != 2,User::getStatus,status)
                .lt(maxPassword != null,User::getPassword,maxPassword)
                .gt(minPassword != null,User::getPassword,minPassword);
        return this.list(userLambdaQueryWrapper); // 原本写法*/
        return lambdaQuery().like(name != null, User::getUsername, name)
                .eq(status != 2, User::getStatus, status)
                .lt(maxPassword != null, User::getPassword, maxPassword)
                .gt(minPassword != null, User::getPassword, minPassword)
//                .list() // 调用list方法，就是都是列表
//                .page() // 如果是分页的话，就直接调用page
//                .exists() // 只是校验是否存在，就级联调用这个方法
                .list();
    }

    @Override
    @Transactional // 加上事务， 一条失败，全部流程恢复。
    public List<User> lambdaUpdateSelf(String id, Integer money) {
        // 1. 查询用户
        User user = this.getById(id);
        // 2.查询用户状态
        if(user == null || user.getStatus() == UserStatus.FORZEN){
            throw new RuntimeException("不存在用户");
        }
        if(user.getPassword() < money){
            throw  new RuntimeException("余额不足");
        }

        int remind = user.getPassword() - money;
        lambdaUpdate()
                .set(User::getPassword,remind)
                .eq(User::getId,id) // 找到id指定值
                .set(remind <=0,User::getStatus,2) // 判断如果小于0 ，就将状态更改
//                .eq(User::getPassword,user.getPassword()) // 乐观锁，就是在执行前，再次判断值是否是自己上次查询的值，因为多线程有可能别人已经修改过值了。
                .update(); // 执行sql语句，一定要写

        return null;
    }

    @Override
    public UserVO queryUserAndAddress(String id) {
        User user = Db.getById(id,User.class); // 用户信息
        // 从address获取信息
        if(user == null || user.getStatus() == UserStatus.FORZEN){
            throw  new RuntimeException("状态有问题！");
        }
        UserVO userVO = BeanUtil.copyProperties(user, UserVO.class);

        List<Address> addresses = iAddressService.list(new LambdaQueryWrapper<Address>().eq(Address::getUserId, id)) ;
        if(CollUtil.isNotEmpty(addresses)){
            List<AddressVO> addressVOS = BeanUtil.copyToList(addresses, AddressVO.class);
            userVO.setAddresses(addressVOS);
        }

        return userVO;
    }

    @Override
    public PageDto<UserVO> queryUserPage(UserQuery2 userQuery2) {
        Integer pageNo = userQuery2.getPageNo();//1
        Integer pageSize = userQuery2.getPageSize(); //1
        // 1.构建分页
      /*  Page<User> page = Page.of(pageNo, pageSize); //1

        // 1.1 分页条件


        // 1.2 排序条件
        if(StrUtil.isNotEmpty(userQuery2.getSortBy())){
            page.addOrder(new OrderItem(userQuery2.getSortBy(),userQuery2.getIsAsc()));
        }else{
            page.addOrder((new OrderItem("update_time",false)));
        }*/
        Page<User> page = userQuery2.toMpPageDefaultUpdateTime();

        // 2.分页查询
        Page<User> paged = lambdaQuery()
                .like(User::getUsername, userQuery2.getName())
                .eq(User::getStatus, userQuery2.getStatus())
                .page(page);

        // 3.1 封装dto
        /*PageDto<UserVO> dto = new PageDto<>();
        dto.setTotal(paged.getTotal());
        dto.setPageNos(paged.getPages());
        List<User> records = paged.getRecords();
        List<UserVO> vos = BeanUtil.copyToList(records, UserVO.class);
        dto.setList(vos);
        return dto;*/
        return   PageDto.of(page,user-> {
            // 1. copy拷贝基础属性
            UserVO vo = BeanUtil.copyProperties(user, UserVO.class);
            // 2.处理特殊逻辑 - 想怎么处理都可以
            vo.setUsername(vo.getUsername().substring(0,vo.getUsername().length() - 2) + "**"); // 把最后两位截取,然后替换为** . 或者处理其他参数也可以.比如处理地址
//            就是把某个参数重新设置, 设置前先提取出来,然后按照指定逻辑处理
            return  vo;
        }); // 最简单版本,直接复制. 和之前逻辑一样,只不过函数拆出来了》
//        return   PageDto.of(page,user-> BeanUtil.copyProperties(user, UserVO.class)); // 最简单版本,直接复制. 和之前逻辑一样,只不过函数拆出来了》
        // 原来版本
//        return   PageDto.of(page,UserVO.class);




//        // 1. 构建分页条件
//        int pageNo = userQuery2.getPageNo();
//        int pageSize = userQuery2.getPageSize();
//        Page<User> page = Page.of(pageNo, pageSize);
//        // 2. 查询 /
//        Page<User> paged = lambdaQuery()
//                .like(userQuery2.getName() != null, User::getUsername, userQuery2.getName())
//                .page(page); // 这里需要添加page属性, LambdaQueryWrapper使用有问题.
//
//        // 3. 封装vo结果
//        PageDto<UserVO> dto = new PageDto<>();
//        dto.setTotal(paged.getTotal());
//        dto.setPageNos(paged.getPages());
//        List<User> records = page.getRecords(); // 这里是User值,需要转换.
//        if(CollUtil.isEmpty(records)){
//            dto.setList(Collections.emptyList());
//        }else{
//            List<UserVO> vos = BeanUtil.copyToList(records, UserVO.class);
//            dto.setList(vos);
//        }
//
//        // 4. 返回结果
//        return dto;
    }


}

























